package com.speedchina.permission.service.sys.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.speedchina.framework.base.TService;
import com.speedchina.framework.helper.Assert;
import com.speedchina.framework.validator.ValidatorHelper;
import com.speedchina.framework.validator.group.UpdateGroup;
import com.speedchina.permission.base.constant.SysConstant;
import com.speedchina.permission.base.sysenum.UserMsgEnum;
import com.speedchina.permission.dao.sys.RoleUserDao;
import com.speedchina.permission.dao.sys.UserDao;
import com.speedchina.permission.dao.sys.UserResourceDao;
import com.speedchina.permission.domain.sys.dto.ResourceDTO;
import com.speedchina.permission.domain.sys.entity.RoleUser;
import com.speedchina.permission.domain.sys.entity.User;
import com.speedchina.permission.domain.sys.entity.UserResource;
import com.speedchina.permission.domain.sys.po.UserPo;
import com.speedchina.permission.service.sys.ResourceService;
import com.speedchina.permission.service.sys.RoleService;
import com.speedchina.permission.service.sys.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;

/**
 * 系统-用户表 服务层实现类
 * @author hank
 * @date 2021-04-08 13:59:05
 */
@Service
public class UserServiceImpl extends TService<UserDao, User> implements UserService{

    @Resource
    RoleUserDao roleUserDao;
    @Resource
    UserResourceDao userResourceDao;
    @Resource
    ResourceService resourceService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    public RoleService roleService;

    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean changePassword(String userId, String oldPwd, String newPwd) {
        User user = baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,userId));
        Assert.isNull(user, UserMsgEnum.USER_NOT_EXIST.getMsg());
        return false;
    }

    /**
     * 1.保存用户基本信息
     * 2.保存用户角色
     * 3.保存用户独立权限
     * @param userPo
     * @return
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public UserPo save(UserPo userPo) {
        User user = baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,userPo.getUsername()));
        Assert.isTrue(user!=null,UserMsgEnum.USERNAME_IS_USE.getMsg());
//        String userId = SnowFlake.generateId().toString();
//        userPo.setId(userId);
        super.saveOrUpdate4AutoGenId(userPo);
//        baseMapper.insert(userPo);
        saveRoleUser(userPo.getRoleIds(),userPo.getId());
        saveUserResource(userPo.getResourceIds(),userPo.getId());
        return userPo;
    }

    /**
     * 修改 用户信息【不处理 password、用户名 】
     * 1、更新用户信息
     * 2、判断角色是否修改，若修改，则批量移除关系之后再重新维护关系表
     * 3、判断独立资源是否修改，若修改，则批量移除关系之后再重新维护关系表
     * @param userPo
     * @return
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean update(UserPo userPo) {
        User user = baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,userPo.getUsername()));
        Assert.isNull(user,UserMsgEnum.USER_NOT_EXIST.getMsg());
        userPo.setPassword(null);
        userPo.setUsername(null);
        baseMapper.updateById(userPo);
        if(isUpdateUserRole(userPo.getRoleIds(),userPo.getId())){
            roleUserDao.delete(new LambdaQueryWrapper<RoleUser>().eq(RoleUser::getUserId,userPo.getId()));
            saveRoleUser(userPo.getRoleIds(),userPo.getId());
        }
        if(isUpdateUserResource(userPo.getResourceIds(),userPo.getId())){
            userResourceDao.delete(new LambdaQueryWrapper<UserResource>().eq(UserResource::getUserId,userPo.getId()));
            saveUserResource(userPo.getResourceIds(),userPo.getId());
        }
        return true;
    }

    /**
     * ！加用户校验下才能执行
     * @param ids
     * @param currentUser
     * @return
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean deleteUserAndLinked(List<Serializable> ids, User currentUser) {
        for (Serializable id:ids){
            Assert.isTrue(id.equals(currentUser.getId()),UserMsgEnum.USER_NOT_ALLOWED_DEL_SEFT.getMsg());
            User user = baseMapper.getUserByIsDefault(id);
            Assert.isTrue(user!=null,UserMsgEnum.NOT_ALLOWED_DEl_DEFAULT_USER.getMsg());
            roleUserDao.delete(new LambdaQueryWrapper<RoleUser>().eq(RoleUser::getUserId,id));
            userResourceDao.delete(new LambdaQueryWrapper<UserResource>().eq(UserResource::getUserId,id));
        }
        deleteBatch(ids);
        return true;
    }

    @Override
    public List<ResourceDTO> queryUserMenuTree(User userPo) {
        User user = baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId,userPo.getId()));
        Assert.isNull(user,UserMsgEnum.USER_NOT_EXIST.getMsg());
        return resourceService.queryUserMenuTree(user);
    }

    @Override
    public User getByUserName(String username) {
        List<User> users = baseMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getUsername,username));
        return users.isEmpty()?null:users.get(0);
    }

    @Override
    public User getByUserPhone(String tel) {
        List<User> users = baseMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getMobile,tel));
        return users.isEmpty()?null:users.get(0);
    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean resetUserPassword(String id, String newPwd) {
        UserPo userPo = new UserPo();
        userPo.setId(id);
        userPo.setPassword(newPwd);
        return update(userPo);
    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean resetUserPassword(String id, String newPassword, String salt) {
        UserPo userPo = new UserPo();
        userPo.setId(id);
        userPo.setPassword(newPassword);
        userPo.setSalt(salt);
        ValidatorHelper.validateEntity(userPo, UpdateGroup.class);
        return baseMapper.updateById(userPo)>0;
    }

    @Override
    public boolean resetUserPasswordOauth2(String id, String newPassword) {
        UserPo userPo = new UserPo();
        userPo.setId(id);
        userPo.setPassword(newPassword);
        return baseMapper.updateById(userPo)>0;
    }

    @Transactional(rollbackFor=Exception.class)
    protected void saveRoleUser(String roleIds,String userId){
        if(!StringUtils.isEmpty(roleIds)){
            String[] roles = roleIds.split(SysConstant.SPLIT_REGEX);
            for(String role:roles){
                RoleUser roleUser = new RoleUser(userId,role);
                roleUserDao.insert(roleUser);
            }
        }
    }
    @Transactional(rollbackFor=Exception.class)
    protected void saveUserResource(String resourceIds,String userId){
        if(!StringUtils.isEmpty(resourceIds)){
            String[] resources = resourceIds.trim().split(SysConstant.SPLIT_REGEX);
            for (String resource:resources){
                UserResource userResource = new UserResource(userId,resource);
                userResourceDao.insert(userResource);
            }
        }
    }

    /**
     * 是否需要更新user-role的关联关系
     * 1.都不为空情况下：
     * @param roleIds
     * @param userId
     * @return
     */
    protected boolean isUpdateUserRole(String roleIds,String userId){
        List<RoleUser> roleUsers = roleUserDao.selectList(new LambdaQueryWrapper<RoleUser>().eq(RoleUser::getUserId,userId));
        if(!StringUtils.isEmpty(roleIds)&&!roleUsers.isEmpty()){
            String[] roles = roleIds.split(SysConstant.SPLIT_REGEX);
            for (String id:roles){
                boolean flag = false;
                for (RoleUser roleUser:roleUsers){
                    if(id.equals(roleUser.getRoleId())){
                        flag = true;
                    }
                }
                if(!flag){
                    return true;
                }
            }
        }
        if(StringUtils.isEmpty(roleIds) && roleUsers.isEmpty()){
            return false;
        }
        return true;
    }
    /**
     * 是否需要更新user-role的关联关系
     * 1.都不为空情况下：
     * @param resourceIds
     * @param userId
     * @return
     */
    protected boolean isUpdateUserResource(String resourceIds,String userId){
        List<UserResource> userResources = userResourceDao.selectList(new LambdaQueryWrapper<UserResource>().eq(UserResource::getUserId,userId));
        if(!StringUtils.isEmpty(resourceIds)&&!userResources.isEmpty()){
            String[] resources = resourceIds.split(SysConstant.SPLIT_REGEX);
            for (String id:resources){
                boolean flag = false;
                for (UserResource userResource:userResources){
                    if(userResource.getResourceId().equals(id)){
                        flag = true;
                    }
                }
                if(!flag){
                    return true;
                }
            }
        }
        if(StringUtils.isEmpty(resourceIds) && userResources.isEmpty()){
            return false;
        }
        return true;
    }

}